home *** CD-ROM | disk | FTP | other *** search
/ Linux Cubed Series 7: Sunsite / Linux Cubed Series 7 - Sunsite Vol 1.iso / system / filesyst / dosfs / dmsdosfs.000 / dmsdosfs / dmsdosfs-0.6.9b / dmsdos_fixdir.c < prev    next >
C/C++ Source or Header  |  1996-07-29  |  4KB  |  146 lines

  1. /*
  2. dmsdos_fixdir.c
  3.  
  4. fixes directory problems under win95 drivespace 3
  5.  
  6. this code actually rearranges shortened directory clusters to avoid
  7. problems with an inode-oriented filesystem
  8.  
  9. ******************************************************************************
  10. DMSDOS (Doublespace/Drivespace compressed MSDOS filesystem) for Linux
  11. written 1995,1996 by Frank Gockel
  12.  
  13.     (C) Copyright 1995,1996 by Frank Gockel
  14.  
  15. Some code of the dmsdos filesystem has been copied from the msdos filesystem
  16. so there are the following additional copyrights:
  17.  
  18.     (C) Copyright 1992,1993 by Werner Almesberger (msdos filesystem)
  19.     (C) Copyright 1994,1995 by Jacques Gelinas (mmap code)
  20.     (C) Copyright 1992-1995 by Linus Torvalds
  21.  
  22. The DMSDOS filesystem was inspired by the THS filesystem (a simple doublespace
  23. DS-0-2 compressed read-only filesystem) written 1994 by Thomas Scheuermann.
  24.  
  25. The DMSDOS filesystem is distributed under the Gnu General Public Licence.
  26. See file COPYING for details.
  27. ******************************************************************************
  28.  
  29. */
  30.  
  31. #include<linux/fs.h>
  32. #include<linux/msdos_fs.h>
  33. #include<linux/malloc.h>
  34. #include<linux/dmsdos_fs.h>
  35.  
  36. extern Dblsb dblsb[];
  37.  
  38. int fix_cluster_length(struct super_block*sb,int cvfnr,int clusternr,int*count)
  39. { Mdfat_entry mde;
  40.   unsigned char * clusterd;
  41.   int i;
  42.   int membytes;
  43.  
  44.   dbl_mdfat_value(sb,clusternr,cvfnr,NULL,&mde);
  45.   if(mde.size_lo_minus_1+1<dblsb[cvfnr].s_sectperclust)
  46.   { printk("DMSDOS: fixdir: fixing cluster %d cvfnr%d\n",clusternr,cvfnr+1);
  47.     
  48.     membytes=dblsb[cvfnr].s_sectperclust*SECTOR_SIZE;
  49.     clusterd=(unsigned char*)MALLOC(membytes);
  50.     if(clusterd==NULL)
  51.     { printk("DMSDOS: fixdir: no memory, aborting!\n");
  52.       return -1;
  53.     }
  54.     if(dmsdos_read_cluster(sb,clusterd,clusternr,cvfnr)<0)
  55.     { printk("DMSDOS: fixdir: read_cluster %d in CVF %d failed, aborting!\n",
  56.              clusternr,cvfnr+1);
  57.       FREE(clusterd);
  58.       return -1;
  59.     }
  60.     for(i=(mde.size_hi_minus_1+1)*SECTOR_SIZE;i<membytes;++i)clusterd[i]=0;
  61.     if(dmsdos_write_cluster(sb,clusterd,membytes,clusternr,0,cvfnr,1)<0)
  62.     { printk("DMSDOS: fixdir: write_cluster %d in CVF %d failed, aborting!\n",
  63.              clusternr,cvfnr+1);
  64.       FREE(clusterd);
  65.       return -1;
  66.     }
  67.     FREE(clusterd);
  68.     ++(*count);
  69.     return 0;
  70.   }
  71.   return 0;
  72. }
  73.  
  74. /* hmmm... I got mail that this recursive function may run out of stack space
  75.    -- cannot imagine -- it doesn't use at least 100 bytes stack --
  76.    so I added the MAXDEPTH check to avoid endless recursion in case of some
  77.    strange failures
  78. */
  79. #define MAXDEPTH 10
  80.  
  81. int fixdir_u(struct super_block*sb,int dirstartclust, int cvfnr,int depth,
  82.              int*count)
  83. { int entrynr;
  84.   unsigned char buf[32];
  85.   int subdirclust,clust;
  86.   unsigned char * pp;
  87.   
  88.   /* don't allow endless recursion in case of unknown failures */
  89.   if(depth>MAXDEPTH)
  90.   { printk("DMSDOS: fixdir: depth > MAXDEPTH, won't go deeper (cluster=%d cvfnr=%d).\n",
  91.            dirstartclust,cvfnr+1);
  92.     return 0; /* don't abort */
  93.   }
  94.  
  95.   clust=dirstartclust;
  96.   do
  97.   { if(fix_cluster_length(sb,cvfnr,clust,count)<0)return -1;
  98.     clust=dbl_fat_nextcluster(sb,clust,cvfnr,NULL);
  99.   }
  100.   while(clust>0);
  101.   
  102.   entrynr=2;   /* don't go through '.' and '..' */
  103.   
  104.   while(read_dbl_direntry(sb,dirstartclust,cvfnr,entrynr++,buf)>0)
  105.   { if(buf[0]!=0&&buf[0]!=0xe5&&((buf[11]&0xF0)==0x10))
  106.     { pp=&(buf[26]);
  107.       subdirclust=CHS(pp);
  108.       if(subdirclust>0)
  109.       { if(fixdir_u(sb,subdirclust,cvfnr,depth+1,count)<0)return -1;
  110.       }
  111.     }  
  112.   }
  113.   
  114.   return 0;
  115. }
  116.  
  117. int fixdir(struct super_block* sb,int cvfnr)
  118. { int entrynr;
  119.   unsigned char buf[32];
  120.   int subdirclust;
  121.   unsigned char * pp;
  122.   int count=0;
  123.   
  124.   printk("DMSDOS: fixdir: scanning directories of CVF %d...\n",cvfnr+1);
  125.  
  126.   entrynr=0;
  127.   
  128.   while(read_dbl_direntry(sb,0,cvfnr,entrynr++,buf)>0)
  129.   { if(buf[0]!=0&&buf[0]!=0xe5&&((buf[11]&0xF0)==0x10))
  130.     { pp=&(buf[26]);
  131.       subdirclust=CHS(pp);
  132.       if(subdirclust>0)
  133.       { if(fixdir_u(sb,subdirclust,cvfnr,0,&count)<0)
  134.         { if(count)printk("DMSDOS: fixdir: aborted after rearranging %d directory clusters successfully.\n",count);
  135.           else printk("DMSDOS: fixdir: aborted - no rearrangements done.\n");
  136.           return -1;
  137.         }
  138.       }
  139.     }  
  140.   }
  141.   if(count)printk("DMSDOS: fixdir: %d directory clusters successfully rearranged.\n",
  142.                    count);
  143.   else printk("DMSDOS: fixdir: no rearrangements necessary.\n");
  144.   return 0;
  145. }
  146.